/** Fichier définissant le cube.
 *
 * Ce fichier contient la définition de la classe Cube.
 *
 * @file Cube.cpp
 * @author Jean-Marc Comby
 * @author Romain Dequesne
 * @author Johan "Solo" Luisier
 *
 * @date 27 Avril 2004
 */
#include "Cube.hpp"

#include "Utils/Erreur.hpp"

#include <cmath>

using namespace std;

/** Constructeur standard.
 *
 * Constructeur qui initialise les 6 plans. On ne donne que deux
 * vecteurs, le troisième est obtenu par produit vectoriel.
 *
 * @param[in] a un des sommets du Cube.
 * @param[in] v1 une des arrêtes du cube.
 * @param[in] v2 direction d'une deuxième arrête, n'a pas besoin d'avoir
 * la même norme ni d'être orthogonal à v1.
 */
Cube::Cube(const Coord& a, const Vecteur& v1, const Vecteur& v2)
    : Parallelepipede( a, v1, Retprojorthonormalisee( v1, v2 ),
                       Renvoiprodvectorielnormalise( v1,Retprojorthonormalisee( v1, v2 ) ) )
{
    Nom = "Cube";
}

/** Destructeur, virtuel pour assurer une séquence de destruction correcte.
 *
 * Le destructeur n'a rien de spécial à faire.
 */
Cube::~Cube()
{}

/** Permet d'obtenir un vecteur orthogonal à la première arrête et qui a la
 * même longueur.
 *
 * "L'anti projection orthogonale" du deuxième vecteur sur le premier est
 * réalisée pour initialiser un vecteur unitaire. Le vecteur renvoyé est alors
 * égal au vecteur unitaire multiplié par la norme du @c premier vecteur.
 *
 * @throw Erreur si l'un des deux vecteur a une norme nulle.
 *
 * @param v1 vecteur référence, la première arrête.
 * @param v2 candidat pour la deuxième arrête.
 *
 * @return un vecteur orthogonal à v1, coplanaire à v1 et v2, dont la
 * norme est égale à celle de v1.
 */
Vecteur Cube::Retprojorthonormalisee(const Vecteur& v1, const Vecteur& v2) const
{
    if ( v2.norme() * v1.norme() < 1.e-7 )	//cas a problemes
    {
        Erreur err(true, 51, "Vecteur d'initialisation du cube de norme = 0.0",
                   "Cube::Renvoiprodvectorielnormalise");
        throw err;
    }
    VecteurU v( v2.OrthoProject( v1 ) );
    Vecteur w( v );
    return w * sqrt( v1.norme() );
}

/** Permet d'obtenir un vecteur orthogonal à une paire de vecteur, avec
 * une norme égale à celle du premier vecteur.
 *
 * Utilise le produit vectoriel des deux vecteurs donnés pour initialiser un
 * vecteur unitaire, qui est ensuite multiplié par la norme du @e premier
 * vecteur.
 *
 * @throw Erreur si l'un des deux vecteur a une norme nulle.
 *
 * @param v1 vecteur référence, la première arrête.
 * @param v2 candidat pour la deuxième arrête.
 * @return un vecteur orthogonal à v1 et v2, de norme égale à celle de
 * v1.
 */
Vecteur Cube::Renvoiprodvectorielnormalise(const Vecteur& v1,
                                           const Vecteur& v2) const
{
    if ( v1.norme() < 1.e-7 )  //cas probleme
    {
        Erreur err(true, 51, "Vecteur d'initialisation du cube de norme = 0.0",
                   "Cube::Renvoiprodvectorielnormalise");
        throw err;
    }
    VecteurU v( v1 ^ v2 );
    Vecteur w( v );
    return w * sqrt( v1.norme() );
}
